using System.Collections.Generic;
using UnityEngine;
using System;

namespace Super
{
	public class TimerManager : BaseSingle<TimerManager>
	{
		private PriorityQueue<TimerNode> timerQueue = new PriorityQueue<TimerNode>();
		private Dictionary<object, List<TimerNode>> dict = new Dictionary<object, List<TimerNode>>();
		private Dictionary<TimerNode, object> nodeDict = new Dictionary<TimerNode, object>();
		private void Update()
		{
			UpdateQueue();
		}

		/// <summary>
		/// 更新时间器，检查优先级最高的时间器
		/// 如果时间器在取消注册集合里，则从集合中取消，检查下一个
		/// 时间器结束，执行结束回调，检查下一个
		/// 时间器间隔结束，执行间隔回调，再次注册，检查下一个
		/// </summary>
		private void UpdateQueue()
		{
			bool overIntervalTime = false;
			bool overEndTime = false;
			if (timerQueue.TryPeek(out TimerNode node))
			{
				if (node.intervalCallBack != null && node.nextIntervalTime <= Time.time)
				{
					overIntervalTime = true;
				}
				if (node.endCallBack != null && node.endTime <= Time.time)
				{
					overEndTime = true;
				}
			}

			if (overIntervalTime || overEndTime)
			{
				if (overIntervalTime)
				{
					timerQueue.Dequeue();
					node.UpdateIntervalEndTime();
					node?.intervalCallBack(node);
					node.intervalCallNum++;
					timerQueue.Enqueue(node);
				}
			
				if (overEndTime)
				{
					node?.endCallBack(node);
					UnRegister(node);
				}
				
				UpdateQueue();
			}
		}

		/* ****************************  时间器相关  ****************************** */
		/// <summary>
		/// 注册时间器
		/// </summary>
		/// <param name="node"></param>
		public static void Register(object target, TimerNode node)
		{
			Ins.timerQueue.Enqueue(node);
			AddTimerNode(target, node);
		}

		public static void ReRegister(object target, TimerNode node)
		{
			UnRegister(node);
			node.intervalCallNum = 0;
			node.UpdateEndTime();
			node.UpdateIntervalEndTime();
			Register(target, node);
		}

		private static void AddTimerNode(object target, TimerNode node)
		{
			if (Ins.dict.TryGetValue(target, out List<TimerNode> timerNodes))
			{
				timerNodes.Add(node);
			}
			else
			{
				timerNodes = new List<TimerNode>() { node };
				Ins.dict.Add(target, timerNodes);
			}

			if (!Ins.nodeDict.ContainsKey(node))
				Ins.nodeDict.Add(node, target);
		}

		/// <summary>
		/// 取消注册时间器
		/// </summary>
		/// <param name="node"></param>
		public static void UnRegister(TimerNode node)
		{
			if (node == null) return;
			object target = Ins.nodeDict[node];
			if (target == null) return;

			Ins.timerQueue.Delete(node);
			if (Ins.dict.TryGetValue(target, out List<TimerNode> timerNodes))
			{
				timerNodes.Remove(node);
			}
			Ins.nodeDict.Remove(node);
		}

		/// <summary>
		/// 取消实例上的所有时间器
		/// </summary>
		/// <param name="target"></param>
		public static void UnRegisterAll(object target)
		{
			if (target == null || CheckIfNotExist())
				return;

			if (Ins.dict.ContainsKey(target))
			{
				var timerNodes = new List<TimerNode>(Ins.dict[target]);
				foreach (var item in timerNodes)
				{
					UnRegister(item);
				}
			}
			Ins.dict.Remove(target);
		}


	}
}
